<template>
  <div>
    <!-- 上传器 -->
    <uploader
      ref="uploader"
      :autoStart=false
      :file-status-text="fileStatusText"
      :options="options"
      class="uploader-ui"
      @file-added="onFileAdded"
      @file-success="onFileSuccess"
      @file-progress="onFileProgress"
      @file-error="onFileError">
      <uploader-unsupport></uploader-unsupport>
      <uploader-drop>
        <div>
          <uploader-btn id="global-uploader-btn" ref="uploadBtn" :attrs="attrs">选择文件<i
            class="el-icon-upload el-icon--right"></i></uploader-btn>
        </div>
      </uploader-drop>
      <uploader-list></uploader-list>
    </uploader>
    <div style="text-align: right">
      <el-button style="right:30px;margin-top: 20px;" type="primary" @click="confirmWindow">确定</el-button>
      <el-button style="right:30px;margin-top: 20px;" type="primary" @click="closeWindow">取消</el-button>
    </div>
  </div>
</template>

<script>
import {ACCEPT_CONFIG} from './common/config'
import SparkMD5 from 'spark-md5'
import {mergeFile} from '@/assets/js/uploadFile'

export default {
  prop: {
    inputFile: {
      type: Array
    }
  },
  watch: {
    inputFile: {
      deep: true,
      handler(newValue, oldValue) {
        //console.log("打出来看看：" + JSON.stringify(newValue))
      }
    }
  },
  data() {
    return {
      options: {
        //目标上传 URL，默认POST
        // target: process.env.VUE_APP_BASE_API+"/uploader/chunk",
        target: process.env.VUE_APP_BASE_API + '/uploader/chunk',
        //分块大小(单位：字节)
        chunkSize: '1024000',
        //上传文件时文件内容的参数名，对应chunk里的Multipart对象名，默认对象名为file
        fileParameterName: 'upfile',
        //失败后最多自动重试上传次数
        maxChunkRetries: 3,
        //是否开启服务器分片校验，对应GET类型同名的target URL
        testChunks: true,
        /*
        服务器分片校验函数，判断秒传及断点续传,传入的参数是Uploader.Chunk实例以及请求响应信息
        reponse码是successStatuses码时，才会进入该方法
        reponse码如果返回的是permanentErrors 中的状态码，不会进入该方法，直接进入onFileError函数 ，并显示上传失败
        reponse码是其他状态码，不会进入该方法，正常走标准上传
        checkChunkUploadedByResponse函数直接return true的话，不再调用上传接口
        */
        checkChunkUploadedByResponse: function (chunk, response_msg) {
          let objMessage = JSON.parse(response_msg)
          if (objMessage.skipUpload) {
            return true
          }
          return (objMessage.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0
        }
      },
      attrs: {
        accept: ACCEPT_CONFIG.getAll()
      },
      fileStatusText: {
        success: '上传成功',
        error: '上传失败',
        uploading: '上传中',
        paused: '暂停',
        waiting: '等待上传'
      }
    }
  },
  methods: {
    confirmWindow() {
      //console.log('----------：' + JSON.stringify(this.inputFile))
      document.querySelector(".uploader-list").childNodes[0].innerHTML = "";
      this.close();
    },
    closeWindow() {
      document.querySelector(".uploader-list").childNodes[0].innerHTML = "";
      //console.log("-------关闭时的inputFile"+JSON.stringify(this.inputFile));
      this.inputFile = [];
      this.close();
    },
    onFileAdded(file) {
      //看看文件是否已经存在了，如果已经存在了则提示并拒绝
      this.computeMD5(file)
    },
    /*
    第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象，它应该包含或者等于成功上传文件；
    第二个参数 file 就是当前成功的 Uploader.File 对象本身；
    第三个参数就是 message 就是服务端响应内容，永远都是字符串；
    第四个参数 chunk 就是 Uploader.Chunk 实例，它就是该文件的最后一个块实例，如果你想得到请求响应码的话，chunk.xhr.status就是
    */
    onFileSuccess(rootFile, file, response, chunk) {
      //refProjectId为预留字段，可关联附件所属目标，例如所属档案，所属工程等
      //document.body.style.cursor="wait";
      file.refProjectId = '123456789'
      var that = this;
      mergeFile(file).then(responseData => {
        // if (responseData.data.code === 415) {
        //   console.log('合并操作未成功，结果码：' + responseData.data.code)
        // }
        if (responseData.code === 200) {
          //上传成功,将文件信息缓存到缓存目录中
          that.inputFile.push(file);
          //console.log('----------：' + JSON.stringify(that.inputFile))
          //document.body.style.cursor="auto";
        }
      })
    },
    onFileError(rootFile, file, response, chunk) {
      //console.log('上传完成后异常信息：' + response)
    },

    /**
     * 计算md5，实现断点续传及秒传
     * @param file
     */
    computeMD5(file) {
      //console.log(file)
      var that = this;
      file.pause()
      if (file.name.split('.').length > 2) {
        that.$message({
          type: 'error',
          showClose: true,
          message: '文件名不能有 " . "'
        })
        var name = file.name;
        for (var i = 0; i < that.inputFile.length; i++) {
          if (that.inputFile[i].name == name) {
            that.inputFile.splice(i, 1);
          }
        }
        file.cancel();
        return;
      }
      //单个文件的大小限制2G
      let fileSizeLimit = 2 * 1024 * 1024 * 1024
      //console.log('文件大小：' + file.size)
      //console.log('限制大小：' + fileSizeLimit)
      if (file.size > fileSizeLimit) {
        that.$message({
          type: 'error',
          showClose: true,
          message: '文件大小不能超过2G'
        })
        var name = file.name;
        for (var i = 0; i < that.inputFile.length; i++) {
          if (that.inputFile[i].name == name) {
            that.inputFile.splice(i, 1);
          }
        }
        file.cancel();
        return;
      }
      if (file.name.indexOf(" ") > -1 || file.name.indexOf("　") > -1) {
        that.$message({
          type: 'error',
          showClose: true,
          message: '文件名不能有空格'
        })
        var name = file.name;
        for (var i = 0; i < that.inputFile.length; i++) {
          if (that.inputFile[i].name == name) {
            that.inputFile.splice(i, 1);
          }
        }
        file.cancel();
        return;
      }
      if (file.size < 1) {
        that.$message({
          type: 'error',
          showClose: true,
          message: '空文档无法上传'
        })
        var name = file.name;
        for (var i = 0; i < that.inputFile.length; i++) {
          if (that.inputFile[i].name == name) {
            that.inputFile.splice(i, 1);
          }
        }
        file.cancel();
        return;
      }

      let fileReader = new FileReader()
      let time = new Date().getTime()
      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
      let currentChunk = 0
      const chunkSize = 10 * 1024 * 1000
      let chunks = Math.ceil(file.size / chunkSize)
      let spark = new SparkMD5.ArrayBuffer()
      //由于计算整个文件的Md5太慢，因此采用只计算第1块文件的md5的方式
      let chunkNumberMD5 = 1

      loadNext()

      fileReader.onload = (e => {
        spark.append(e.target.result)

        if (currentChunk < chunkNumberMD5) {
          loadNext()
        } else {
          let md5 = spark.end()
          file.uniqueIdentifier = md5
          //随机生成8位随机数
          file.uniqueIdentifier = parseInt(Math.random() * 100000000);
          while (file.uniqueIdentifier.length < 8) {
            file.uniqueIdentifier = file.uniqueIdentifier + 0;
          }
          file.resume()
          /*console.log(`MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`)
          console.log('----------：' + JSON.stringify(that.inputFile))
          当文件名不同，但是文件内部的md5一致时，会引起重复，所以需要剔除相同md5的文件
          for(var i=0;i<that.inputFile.length;i++){
            if(that.inputFile[i].uniqueIdentifier==file.uniqueIdentifier){
              that.inputFile.splice(i,1);
              that.$message({
                type:'error',
                showClose: true,
                message: '同时上传的文件内容相同，所以只能上传一个'
              })
              file.cancel();

              //将页面显示的文件删掉
              var lis=document.querySelector(".uploader-list").childNodes[0].childNodes;
              for(var k=0;k<lis.length;k++){
                console.log("--------fghghfg"+lis[k].innerText);
                if(lis[k].innerText==file.name){
                  lis[k].remove();
                }
              }
              return;
            }
          }*/
        }
      })

      fileReader.onerror = function () {
        that.error(`文件${file.name}读取出错，请检查该文件`)
        file.cancel()
      }

      function loadNext() {
        let start = currentChunk * chunkSize
        let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize

        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
        currentChunk++
        //console.log('计算第' + currentChunk + '块')
      }
    },
    close() {
      this.$parent.$parent.closeDialog(this.inputFile);
      this.inputFile = [];//用完以后清空
    },
    error(msg) {
      this.$notify({
        title: '错误',
        message: msg,
        type: 'error',
        duration: 2000
      })
    },
    onFileProgress() {

    }
  },
  mounted() {
    this.inputFile = [];
    document.querySelector(".uploader-list").childNodes[0].innerHTML = "";
  }
}
</script>

<style>
.uploader-ui {
  padding: 15px;
  margin: 40px auto 0;
  font-size: 12px;
  font-family: Microsoft YaHei;
  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
}

.uploader-ui .uploader-btn {
  margin-right: 4px;
  font-size: 12px;
  border-radius: 3px;
  color: #FFF;
  background-color: #409EFF;
  border-color: #409EFF;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
}

.uploader-ui .uploader-list {
  max-height: 440px;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
}
</style>
